package orm.service;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisConnectionException;

import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.Set;

/**
 * 封装redis 缓存服务器服务接口
 * UserController: Ashin.
 * Date：2016/8/8
 * Time：16:20
 */
@Component
public class RedisService {

    Logger log = Logger.getLogger(RedisService.class);

    //操作redis客户端
    private static Jedis jedis;

    public static int TWO_HOURS = 7200;

    /**
     * 通过key删除（字节）
     *
     * @param key
     */
    public void del(byte[] key) {
        this.getJedis().del(key);
    }

    /**
     * 通过key删除
     *
     * @param key
     */
    public void del(String key) {
        this.getJedis().del(key);
    }

    /**
     * 添加key value 并且设置存活时间(byte)
     *
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(byte[] key, byte[] value, int liveTime) {
        this.set(key, value);
        this.getJedis().expire(key, liveTime);
    }

    /**
     * 添加key value 并且设置存活时间
     *
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(String key, String value, int liveTime) {
        this.set(key, value);
        this.getJedis().expire(key, liveTime);
    }

    /**
     * 添加key value
     *
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        this.getJedis().set(key, value);
    }

    /**
     * 添加key value (字节)(序列化)
     *
     * @param key
     * @param value
     */
    public void set(byte[] key, byte[] value) {
        this.getJedis().set(key, value);
    }

    /**
     * 获取redis value (String)
     *
     * @param key
     * @return
     */
    public String get(String key) {
        String value = this.getJedis().get(key);
        return value;
    }

    /**
     * 获取redis value (byte [] )(反序列化)
     *
     * @param key
     * @return
     */
    public byte[] get(byte[] key) {
        return this.getJedis().get(key);
    }

    /**
     * 通过正则匹配keys
     *
     * @param pattern
     * @return
     */
    public Set<String> keys(String pattern) {
        return this.getJedis().keys(pattern);
    }

    /**
     * 检查key是否已经存在
     *
     * @param key
     * @return
     */
    public boolean exists(String key) {
        return this.getJedis().exists(key);
    }

    /**
     * 清空redis 所有数据
     *
     * @return
     */
    public String flushDB() {
        return this.getJedis().flushDB();
    }

    /**
     * 批量模糊刪除
     * @param pre_str
     */
    public void batchDel(String pre_str) {
        Set<String> set = this.getJedis().keys(pre_str + "*");
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String keyStr = it.next();
            this.getJedis().del(keyStr);
        }
    }

    /**
     * 返回key的剩余时间
     * @param key
     * @return
     */
    public long timeRemaining(String key){
        try {
            return this.getJedis().ttl(key);
        }catch (Exception e){
            return -10;
        }
    }

    /**
     * 返回key的剩余时间
     * @param key
     * @return
     */
    public long timeRemaining(byte[] key){
        try {
            return this.getJedis().ttl(key);
        }catch (Exception e){
            return -10;
        }
    }

    /**
     * 查看redis里有多少数据
     */
    public long dbSize() {
        return this.getJedis().dbSize();
    }

    /**
     * 检查是否连接成功
     *
     * @return
     */
    public String ping() {
        return this.getJedis().ping();
    }

    /**
     * 获取一个jedis 客户端
     *
     * @return
     */
//    private Jedis getJedis() {
//        if (jedis == null) {
//            return jedisConnectionFactory.getShardInfo().createResource();
//        }
//        return jedis;
//    }

    public Jedis getJedis()
    {
        int timeoutCount = 0;
        if(jedis != null)
            return jedis;
        while (true) // 如果是网络超时则多试几次
        {
            try
            {
                Jedis jedis = jedisConnectionFactory.getShardInfo().createResource();
                return jedis;
            } catch (Exception e)
            {
                // 底层原因是SocketTimeoutException，不过redis已经捕捉且抛出JedisConnectionException，不继承于前者
                if (e instanceof JedisConnectionException || e instanceof SocketTimeoutException)
                {
                    timeoutCount++;
                    log.warn("getJedis timeoutCount=" + timeoutCount, e);
                    if (timeoutCount > 3)
                    {
                        break;
                    }
                }else
                {
                    log.error("getJedis error", e);
                    break;
                }
            }
        }
        return null;
    }

    private RedisService() {

    }

    @Autowired
    @Qualifier("connectionFactory")
    private JedisConnectionFactory jedisConnectionFactory;
}
